#pragma once
#include<unordered_map>
#include<cassert>
#include<fstream>
#include<iostream>
#include<vector>
#include<string>
#include<cstdlib>
#include"../comm/spdlog.hpp"
#include"../comm/util.hpp"


namespace y_model
{
    //题目信息
    struct Question
    {
        std::string number;//编号
        std::string title;//标题
        std::string star;//难度
        int cpu_limit;//时间要求
        int mem_limit;//空间要求
        std::string desc;//题目描述
        std::string header;//题目预设给用户在线编辑器代码
        std::string tail;//测试用例代码
    };

    const std::string question_list="./questions/questions.list";
    const std::string questions_path = "./questions/";

    class Model
    {
    public:
        Model()
        {
            //把题目列表和数据加载到客户端
            assert(LoadQuestionList(question_list));
        }
        ~Model(){}

        //获取全部题目
        bool GetAllQuestions(std::vector<Question>& out)
        {
            if(questions.size()==0)
            {
                ERROR("用户题库获取失败");
                return false;
            }

            for(const auto& q:questions)
            {
                out.push_back(q.second);
            }
            return true;
        }

        //获取单个题目
        bool GetOneQuestion(const std::string& number,Question& q)
        {
            const auto& iter=questions.find(number);
            if(iter==questions.end())
            {
                ERROR("用户获取题目失败，题目编号为：{}",number);
                return false;
            }
            q=iter->second;
            return true;
        }
        
    private:
        bool LoadQuestionList(const std::string question_list)
        {
            std::ifstream in(question_list);
            if(!in.is_open())
            {
                FATAL("加载题库失败");
                return false;
            }

            std::string line;
            while(getline(in,line))
            {
                std::vector<std::string> tokens;
                y_util::StringUtil::SqlitString(line,&tokens," ");
                if(tokens.size()!=5)
                {
                    WARN("加载部分题目失败，检查文件格式");
                    continue;
                }

                Question q;
                q.number=tokens[0];
                q.title=tokens[1];
                q.star=tokens[2];
                q.cpu_limit=std::atoi(tokens[3].c_str());
                q.mem_limit=std::atoi(tokens[4].c_str());

                std::string path=questions_path;
                path+=q.number;
                path+="/";

                y_util::FileUtil::ReadFile(path+"desc.txt",&(q.desc),true);
                y_util::FileUtil::ReadFile(path+"header.cpp",&(q.header),true);
                y_util::FileUtil::ReadFile(path+"tail.cpp",&(q.tail),true);

                questions.insert({q.number,q});
            }
            INFO("加载题库...成功！");
            in.close();

            return true;
        }
    private:
        std::unordered_map<std::string,Question> questions;
    };
}